
package com.idealighter.game.games.xzdd.manager;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.core.tuple.Pair;
import com.idealighter.game.dictionary.dic.XzddMultipleDic;
import com.idealighter.game.dictionary.dic.XzddRoomDic;
import com.idealighter.game.event.manager.EventMgr;
import com.idealighter.game.gamehall.event.RoomMemInfoUpdateEvent;
import com.idealighter.game.games.xzdd.struct.XzddGangType;
import com.idealighter.game.games.xzdd.struct.XzddHuType;
import com.idealighter.game.games.xzdd.struct.XzddPlayerBill;
import com.idealighter.game.games.xzdd.struct.XzddSeat;
import com.idealighter.game.games.xzdd.struct.XzddSeatCards;
import com.idealighter.game.games.xzdd.struct.XzddTable;
import com.idealighter.game.log.core.LogReason;
import com.idealighter.game.player.manager.PlayerMgr;
import com.idealighter.game.player.service.bo.PlayerBo;

import java.util.ArrayList;
import java.util.List;

/**
 * 血战到底结算器，主要结算胡牌的明细和游戏结束后的结算明细 .
 * 
 * @date 2016年9月14日 上午11:23:15
 *
 */
@Singleton
public class XzddBiller {

  // 清一色加翻id
  public static final int QING_YI_SE_MULTIPLE_ID = 10;
  // 四合加翻id
  public static final int SI_HE_MULTIPLE_ID = 11;
  // 查花猪加翻id
  public static final int CHA_HUA_ZHU_MULTIPLE_ID = 32;
  // 退出游戏赔偿翻数
  public static final int EXIT_GAME_MULTIPLE = 16;

  @Inject
  private XzddRoomDic roomDic;
  @Inject
  private XzddMultipleDic multipleDic;
  @Inject
  private PlayerMgr playerMgr;
  @Inject
  private EventMgr eventMgr;


  /**
   * 退出游戏结算 .
   * 
   * @param seat 座位信息.
   */
  public void billExitGame(XzddSeat seat) {
    XzddTable table = seat.table;
    XzddPlayerBill playerBill = table.playerBills.get(seat.getPlayerId());
    playerBill.type = 4;

    // 翻数
    int multiple = EXIT_GAME_MULTIPLE;
    // 基础金币
    int baseGold = roomDic.get(table.room.getId().intValue()).getMinOne();
    int gold = multiple * baseGold;

    playerBill.golds -= gold;
    playerMgr.addGold(seat.getPlayerId(), -gold, LogReason.XZDD_EXIT_GAME);
    eventMgr.post(new RoomMemInfoUpdateEvent(playerMgr.getPlayer(seat.getPlayerId())));
  }

  /**
   * 结算杠 .
   * 
   * @param winer .
   * @param gangType .
   */
  public void billGang(XzddSeat winer, XzddGangType gangType) {
    XzddTable table = winer.table;
    // 输家列表
    List<Pair<Long, String>> losePlayers = new ArrayList<>();
    switch (gangType) {
      case AN_GANG:
        for (XzddSeat s : table.seats) {
          if (s != winer && s.getPlayerId() > 0 && !s.over) {
            losePlayers.add(new Pair<>(s.getPlayerId(), s.getPlayerName()));
          }
        }
        break;
      case MIAN_XIA_GANG:
        for (XzddSeat s : table.seats) {
          if (s != winer && s.getPlayerId() > 0 && !s.over) {
            losePlayers.add(new Pair<>(s.getPlayerId(), s.getPlayerName()));
          }
        }
        break;
      case ZHI_GANG:
        PlayerBo playerDom = playerMgr.selectPlayer(table.prePlayer);
        losePlayers.add(new Pair<>(playerDom.getId(), playerDom.getPlayerName()));
        break;
      default:
        break;
    }

    // 翻数
    int multiple = gangType.multiple();
    // 基础金币
    int baseGold = roomDic.get(winer.table.room.getId().intValue()).getMinOne();
    int gold = multiple * baseGold;

    XzddPlayerBill winerBill = table.playerBills.get(winer.getPlayerId());
    for (Pair<Long, String> pair : losePlayers) {
      final long loserPlayerId = pair.v1;
      String loserPlayerName = pair.v2;

      winerBill.golds += gold;
      winerBill.billedPlayer.put(loserPlayerName,
          winerBill.billedPlayer.getOrDefault(loserPlayerName, 0L) + gold);
      playerMgr.addGold(winer.getPlayerId(), gold,
          gangType == XzddGangType.AN_GANG ? LogReason.XZDD_XIA_YU : LogReason.XZDD_GUA_FENG);
      eventMgr.post(new RoomMemInfoUpdateEvent(playerMgr.getPlayer(winer.getPlayerId())));

      XzddPlayerBill loserBill = table.playerBills.get(loserPlayerId);
      loserBill.golds -= gold;
      loserBill.billedPlayer.put(winer.getPlayerName(),
          loserBill.billedPlayer.getOrDefault(winer.getPlayerName(), 0L) - gold);
      playerMgr.addGold(loserPlayerId, -gold,
          gangType == XzddGangType.AN_GANG ? LogReason.XZDD_XIA_YU : LogReason.XZDD_GUA_FENG);
      eventMgr.post(new RoomMemInfoUpdateEvent(playerMgr.getPlayer(loserPlayerId)));
    }
  }

  /**
   * 结算胡 .
   * 
   * @param winer .
   * @param multiple . 合计倍数
   * @param gold . 合计金币
   * @param isZiMo .
   * @return 被胡的人数
   */
  public int billHu(XzddSeat winer, int multiple, int gold, boolean isZiMo, XzddHuType huType) {
    XzddTable table = winer.table;
    // 输家列表
    List<Pair<Long, String>> losePlayers = new ArrayList<>();

    if (isZiMo) { // 是否自摸?
      for (XzddSeat s : table.seats) {
        if (s != winer && s.getPlayerId() > 0 && !s.over) {
          losePlayers.add(new Pair<>(s.getPlayerId(), s.getPlayerName()));
        }
      }
    } else {
      // 输家
      long loserId = 0;
      if (huType == XzddHuType.QIANG_GANG_HU) { // 抢杠胡是杠的那个玩家
        loserId = table.gangedSeat().getPlayerId();
      } else {
        loserId = table.prePlayer;
      }
      PlayerBo prePlayerDom = playerMgr.selectPlayer(loserId);
      losePlayers.add(new Pair<>(prePlayerDom.getId(), prePlayerDom.getPlayerName()));
    }

    XzddPlayerBill winerBill = table.playerBills.get(winer.getPlayerId());
    winerBill.type = 0;
    for (Pair<Long, String> pair : losePlayers) {
      final long loserPlayerId = pair.v1;
      String loserPlayerName = pair.v2;

      winerBill.golds += gold;
      winerBill.billedPlayer.put(loserPlayerName,
          winerBill.billedPlayer.getOrDefault(loserPlayerName, 0L) + gold);
      playerMgr.addGold(winer.getPlayerId(), gold, LogReason.XZDD_HU);
      eventMgr.post(new RoomMemInfoUpdateEvent(playerMgr.getPlayer(winer.getPlayerId())));

      XzddPlayerBill loserBill = table.playerBills.get(loserPlayerId);
      loserBill.golds -= gold;
      loserBill.billedPlayer.put(winer.getPlayerName(),
          loserBill.billedPlayer.getOrDefault(winer.getPlayerName(), 0L) - gold);
      playerMgr.addGold(loserPlayerId, -gold, LogReason.XZDD_HU);
      eventMgr.post(new RoomMemInfoUpdateEvent(playerMgr.getPlayer(loserPlayerId)));
    }

    return losePlayers.size();
  }

  /**
   * 结算查牌，优先查花猪再查听 .
   * 
   * @param seat 座位信息.
   */
  public void billChaPai(XzddSeat seat) {
    XzddSeatCards cards = seat.cards;
    XzddTable table = seat.table;

    // 是否花猪
    boolean huaZhu = cards.isHuaZhu();
    // 是否无听
    boolean wuTing = cards.isWuTing();
    // 基础金币
    int baseGold = roomDic.get(table.room.getId().intValue()).getMinOne();
    // 花猪翻数
    int huaZhuMultiple = multipleDic.get(CHA_HUA_ZHU_MULTIPLE_ID).getMultiple();

    if (huaZhu || wuTing) {
      XzddPlayerBill loserBill = table.playerBills.get(seat.getPlayerId());
      loserBill.type = huaZhu ? 3 : 2;

      for (XzddSeat s : table.seats) {
        if (s != seat && s.getPlayerId() > 0 && !s.over && s.cards.getHuMjs().size() > 0) { // 有听?
          final long winerPlayerId = s.getPlayerId();
          String winerPlayerName = s.getPlayerName();
          // 赔偿的金币,花猪直接倍数，叫是翻翻
          int gold = huaZhu ? huaZhuMultiple * baseGold : baseGold << s.cards.maxHuPaiMultiple();

          /*
           * seat(花猪或无听玩家)结算 .
           */
          loserBill.golds -= gold;
          loserBill.billedPlayer.put(winerPlayerName,
              loserBill.billedPlayer.getOrDefault(winerPlayerName, 0L) - gold);
          playerMgr.addGold(seat.getPlayerId(), -gold, LogReason.XZDD_CHA_PAI);
          eventMgr.post(new RoomMemInfoUpdateEvent(playerMgr.getPlayer(seat.getPlayerId())));

          /*
           * 有叫玩家结算 .
           */
          XzddPlayerBill winerBill = table.playerBills.get(winerPlayerId);
          winerBill.type = 1;
          winerBill.golds += gold;
          winerBill.billedPlayer.put(seat.getPlayerName(),
              winerBill.billedPlayer.getOrDefault(seat.getPlayerName(), 0L) + gold);
          playerMgr.addGold(winerPlayerId, gold, LogReason.XZDD_CHA_PAI);
          eventMgr.post(new RoomMemInfoUpdateEvent(playerMgr.getPlayer(winerPlayerId)));
        }
      }
    }
  }

}
